#include "ThreadManager.h"

namespace qy
{

ThreadManager::ThreadManager(int conThreadCount)
: m_conThreadCount(conThreadCount)
{
    pthread_mutex_init(&m_threadsMutex, NULL);
	pthread_cond_init(&m_threadsCond, NULL);
}

ThreadManager::~ThreadManager()
{
    pthread_cond_destroy(&m_threadsCond);
    pthread_mutex_destroy(&m_threadsMutex);
}

int ThreadManager::run()
{
    struct timespec timeout;
	time_t now;

    while(true)
	{
	    for(std::list<Thread*>::iterator it = m_workingThreads.begin(); it != m_workingThreads.end();)
		{
		    if((*it)->isRunning() == false)
			{
			    it = m_workingThreads.erase(it);
			}
			else
			{
			    it++;
			}
		}

	    pthread_mutex_lock(&m_threadsMutex);

        int i = 0;
		while(i < m_conThreadCount - m_workingThreads.size())
		{
		    if(m_waitingThreads.size() == 0)
			{
			    break;
			}

			Thread *pThread = m_waitingThreads.front();
			pThread->start();
			m_workingThreads.push_back(pThread);
			m_waitingThreads.pop();
		}
		time(&now);
		timeout.tv_sec = now + 3;
		if(m_workingThreads.size() == 0)
		{
		    timeout.tv_sec += 3; //waiting for 3 seconds more if no child thread is working.
		}
		timeout.tv_nsec = 0;
		//if use _wait instead of _timedwait, this thread will be blocked forever if the child threads get finished before _wait is called. 
		//Because, the child threads only call _cond_signal one time when they get over, so if all signals missed, the thread will wait here forever
		//In case of that, _timedwait should be used here.
		pthread_cond_timedwait(&m_threadsCond, &m_threadsMutex, &timeout);
		//pthread_cond_wait(&m_threadsCond, &m_threadsMutex);
		pthread_mutex_unlock(&m_threadsMutex);
	}
}

void ThreadManager::addThread(Thread *pThread)
{
    pthread_mutex_lock(&m_threadsMutex);
	m_waitingThreads.push(pThread);
	pThread->setOverCond(&m_threadsCond);
	pthread_mutex_unlock(&m_threadsMutex);
}

}
